const fs = require("fs");
const path = require("path");
const Koa = require('koa')
const Router = require('@koa/router');
const bodyParser = require('koa-bodyparser')
const koaLogger = require('koa-logger')
const jwt = require('koa-jwt')
const { onerror } = require('koa-onerror');
const koaStatic = require('koa-static');
const cors = require('koa2-cors')
const Redis = require('ioredis');
const compress = require('koa-compress')
const helmet = require('koa-helmet');
const ratelimit = require('koa-ratelimit');
const logger = require('./middleware/logger');
require('dotenv').config();
const { dateFormat } = require('./utils');
const log4j = require('./utils/log4j');

const app = new Koa();
const router = new Router();

app.use(helmet());
app.use(ratelimit({
  // driver: 'redis',
  // db: new Redis(),
  driver: 'memory',
  db: new Map(),
  duration: 60000,
  errorMessage: '系统繁忙',
  id: (ctx) => ctx.ip,
  headers: {
    remaining: 'Rate-Limit-Remaining',
    reset: 'Rate-Limit-Reset',
    total: 'Rate-Limit-Total'
  },
  max: 1000,
  disableHeader: false
}));

app.use(compress({
  filter (content_type) {
  	return /text/i.test(content_type)
  },
  threshold: 2048,
  gzip: {
    flush: require('zlib').constants.Z_SYNC_FLUSH
  },
  deflate: {
    flush: require('zlib').constants.Z_SYNC_FLUSH,
  },
  br: false // disable brotli
}))

app.use(koaStatic(path.resolve(__dirname, '../public')));
app.use(koaStatic(path.resolve(__dirname, '../logs')));

app.use(logger)
onerror(app)
app.use(bodyParser({
  enableTypes: ['json', 'form', 'text']
}))
app.use(koaLogger(str => {
  console.log(dateFormat(new Date(), 'hh:mm:ss:S') + str)
}))

app.use(cors({
  origin: function(ctx) {
    const whiteList = ['http://test.com','http://localhost:3000'];
    let url = ctx.header.host;
    if(whiteList.includes(url)){
      return url // 注意，这里域名末尾不能带/，否则不成功，所以在之前我把/通过 substr 干掉了
    }
  },
  maxAge: 5 * 24 * 60 * 60,
  credentials: true, //是否允许发送Cookie
  allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
  allowHeaders: ['Content-Type', 'Authorization', 'Accept', 'X-Requested-With'],
  exposeHeaders: ['Authorization', 'WWW-Authenticate', 'Server-Authorization']
}))

// router.use(jwt({
//   secret: 'ChenNick',
//   cookie: 'token', // 从 cookie 中获取 token
//   key: 'userinfo', // ctx.state[key] 获取 jsonwebtoken.sign 注册的用户信息
//   debug: true // 开启debug可以看到准确的错误信息
// }).unless({ path: [/^\/public/] })) // 以 public 开头的请求地址不使用 jwt 中间件

app.on('error', (err, ctx) => {
  log4j.logError(err)
  console.error(err);
	ctx.body = { 
    code: 500,
    msg: '系统异常'
  }
});

fs.readdirSync(path.join(__dirname, '/routes')).forEach((item) => {
  let file = require('./routes/' + item);
  router.use(file.routes());
});
app.use(router.routes()).use(router.allowedMethods())

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server is running at http://localhost:${PORT}`)
})